package cn.tedu.store.util;

import cn.tedu.store.entity.UserEntity;
import cn.tedu.store.service.ex.EmptyArgumentException;
import cn.tedu.store.service.ex.LoginException;
import cn.tedu.store.service.ex.ServiceException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    @Autowired
    private StringRedisTemplate template; // Springboot提供的访问redis的工具类

    private static final long DEFAULT_SESSION_TIMEOUT=30; // 会话状态默认超时时间 30分钟
    private static final boolean AUTO_EXTEND_SESSION_TIMEOUT=true; // 是否自动延长会话超时时间
    public static final String USER_INFO_COOKIE_NAME="EM_TICKET";

    // jackson提供的将对象转换成json字符串的工具，线程安全
    ObjectMapper mapper=new ObjectMapper();

    /**
     * 将用户会话状态保存到redis中
     * 使用"EM_TICKET_+时间戳+用户名的格式"的格式作为redis中数据的key
     * 数据默认有效时间为30分钟
     * @param user 用户信息
     * @return ticket redis中保存数据的key
     * @throws EmptyArgumentException
     */
    public String saveUserInfo(UserEntity user)
            throws EmptyArgumentException {
        ValueOperations<String, String> stringOps = template.opsForValue();
        if(user==null || StringUtils.isEmpty(user.getUsername())){
            throw new EmptyArgumentException("保存用户登录状态异常！用户信息为空");
        }
        // 敏感信息置null
        user.setPassword(null);
        user.setSalt(null);
        // 生成key
        String ticket="EM_TICKET_"+System.currentTimeMillis()+user.getUsername();
        try {
            String value=mapper.writeValueAsString(user);
            //将key-value ticket-userJson存放到redis 超时存储
            stringOps.set(ticket,value,DEFAULT_SESSION_TIMEOUT, TimeUnit.MINUTES);
        } catch (JsonProcessingException e) {
            throw new ServiceException("保存用户登录状态异常！数据转换异常："+e.getMessage());
        }
        return ticket;
    }

    /**
     * 从Redis中查询用户登录信息
     * @param ticket redis中的key
     * @return user对象 或 null
     * @throws ServiceException
     */
    public UserEntity getUserInfo(String ticket)
        throws ServiceException{
        // 非空验证
        if(StringUtils.isEmpty(ticket)){
            throw new EmptyArgumentException("读取用户会话状态异常！会话已超时");
        }
        //调用业务层获取userJson,不一定获取到,因为有可能已经超时了
        String userJson=template.opsForValue().get(ticket);
        if(userJson==null){
            throw new LoginException("读取用户会话状态异常！会话已超时");
        }
        UserEntity entity=null;
        if(userJson!=null){
            try {
                entity=mapper.readValue(userJson,UserEntity.class);
                if(AUTO_EXTEND_SESSION_TIMEOUT){ // 延长会话有效期
                    template.expire(ticket,DEFAULT_SESSION_TIMEOUT,TimeUnit.MINUTES);
                }
            } catch (JsonProcessingException e) {
                throw new ServiceException("读取用户会话状态异常！数据转换异常："+e.getMessage());
            }
        }
        return entity;
    }

}
